package com.rslai.base.tool.servertest.objectfactory;

import com.alibaba.fastjson.JSON;
import com.rslai.base.tool.servertest.model.KeyValueStore;
import com.rslai.base.tool.servertest.util.MapUtils;
import com.rslai.base.tool.servertest.util.ReflectionUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

public class MapFactory extends InstanceFactory {
    protected Object create(Type type, Object value) {
        if (value == null)
            return null;
        Map temp = new LinkedHashMap();
        if (value instanceof Map)
            temp.putAll((Map) value);
        else if (value instanceof List) {
            List items = (List) value;
            KeyValueStore item;
            for (Iterator i$ = items.iterator(); i$.hasNext(); temp.put(item.getName(), item.getValue()))
                item = (KeyValueStore) i$.next();

        } else if (isJson(value)) {
            Map jsonMap = (Map) JSON.parse(value.toString());
            temp.putAll(jsonMap);
        }
        return createMap(type, temp);
    }

    private Object createMap(Type type, Map<Object, Object> temp) {
        Map result = MapUtils.init(type);
        Type keyClass = extractKeyClass(type, temp);
        Type valueClass = extractValueClass(type, temp);
        for (Map.Entry entry : temp.entrySet()) {
            if ((!isKeyClassElement(entry)) &&
                    (!isValueClassElement(entry)))
                result.put(BeanUtils.create(keyClass, entry.getKey()), BeanUtils.create(valueClass, entry.getValue()));
        }
        return result;
    }

    private boolean isValueClassElement(Map.Entry<Object, Object> entry) {
        return entry.getKey().equals("__valueClass");
    }

    private boolean isKeyClassElement(Map.Entry<Object, Object> entry) {
        return entry.getKey().equals("__keyClass");
    }

    private Type extractKeyClass(Type type, Map<Object, Object> temp) {
        String keyClassName = (String) temp.get("__keyClass");
        if (StringUtils.isNotBlank(keyClassName)) {
            return ReflectionUtils.loadClass(keyClassName);
        }
        if ((type instanceof ParameterizedType)) {
            return ((ParameterizedType) type).getActualTypeArguments()[0];
        }
        return String.class;
    }

    private Type extractValueClass(Type type, Map<Object, Object> temp) {
        String valueClassName = (String) temp.get("__valueClass");
        if (StringUtils.isNotBlank(valueClassName)) {
            return ReflectionUtils.loadClass(valueClassName);
        }
        if ((type instanceof ParameterizedType)) {
            return ((ParameterizedType) type).getActualTypeArguments()[1];
        }
        return Object.class;
    }

    private boolean isJson(Object value) {
        if (!(value instanceof String)) return false;
        String json = value.toString();
        return (json.startsWith("{")) && (json.endsWith("}"));
    }

    protected boolean support(Type type) {
        if ((type instanceof Class)) {
            return Map.class.isAssignableFrom((Class) type);
        }
        if ((type instanceof ParameterizedType)) {
            Class rawType = (Class) ((ParameterizedType) type).getRawType();
            return Map.class.isAssignableFrom(rawType);
        }
        return false;
    }
}